package com.fingard.net;

import com.fingard.FGBiz;
import com.fingard.diagnostics.LogHelper;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

public class TcpPortClient {

	private String ip = "";
	private int port = 0;
	public Socket socket = null;
	ITcpClient tcpClient = null;
	public OutputStream tmpOutput = null;
	public InputStream tmpInput = null;
	public TcpPortClient(String p_ip, int p_port, ITcpClient p_client){
		ip = p_ip;
		port = p_port;
		tcpClient = p_client;
	}
	
	private int initContentStartIndex = 0;
	public void setContentStartIndex(int p_idx){
		initContentStartIndex = p_idx;
	}
	
	/**超时时间，单位：毫秒，默认100000毫秒=100秒*/
	public int timeoutMil = 100000;
	
	public TcpReceiver sendMessageSync(byte[] p_sendBytes) throws Exception{
		TcpReceiver retReceiver = new TcpReceiver();
		if(initContentStartIndex != 0){
			retReceiver.contentStartIndex = initContentStartIndex;
		}
		try {
			socket = new Socket(ip, port);
			socket.setSoTimeout(timeoutMil);
		} catch (Throwable e) {
			retReceiver.connState = ConnState.FAIL;
			retReceiver.connMsg = LogHelper.getStackTrace(e);
			FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
			return retReceiver;
		}
		try {
			OutputStream tmpOutput = socket.getOutputStream();
			tmpOutput.write(p_sendBytes);
			tmpOutput.close();
		} catch (IOException e) {
			FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
			retReceiver.connMsg = LogHelper.getStackTrace(e);
		}finally{
			socket.close();
		}
		return retReceiver;
	}
	
	public TcpReceiver sendMessage(byte[] p_sendBytes) throws Exception{
		return sendMessage(null,p_sendBytes);
	}

	/**发送和接收之后，不关闭连接*/
    public TcpReceiver sendMessageClose(byte[] p_sendBytes) throws Exception{
        TcpReceiver retReceiver = new TcpReceiver();
        if(initContentStartIndex != 0){
            retReceiver.contentStartIndex = initContentStartIndex;
        }
        try {
            if (socket == null) {
                socket = new Socket(ip, port);
                socket.setSoTimeout(timeoutMil);//180000
            }
        }
        catch (Exception e) {
            retReceiver.connState = ConnState.FAIL;
            retReceiver.connMsg = e.getMessage();
            return retReceiver;
        }
        try {
        	if (tmpOutput == null) {
				tmpOutput = socket.getOutputStream();
			}
            if (tmpInput == null) {
				tmpInput = socket.getInputStream();
			}
            tmpOutput.write(p_sendBytes);

            retReceiver.recBytes = new byte[2048];//2K
            int tmpOffSet = 0;

            while(!retReceiver.isCompleted){
                int tmpReadLen = tmpInput.read(retReceiver.recBytes, tmpOffSet, retReceiver.recBytes.length - tmpOffSet);
                if(tmpReadLen<=0){
                    break;
                }
                tmpOffSet += tmpReadLen;
                retReceiver.readedLength = retReceiver.readedLength + tmpReadLen;
                if(retReceiver.contentLength == -1 || retReceiver.contentStartIndex < 0){
                    tcpClient.getContentLength(retReceiver);
                }

                if (retReceiver.contentLength > 0)
                {
                    if (retReceiver.recBytes.length < retReceiver.contentLength + retReceiver.contentStartIndex)
                    {
                        byte[] tmpUnionInfo = new byte[retReceiver.contentLength + retReceiver.contentStartIndex];//一次性分配内存
                        System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo, 0, tmpOffSet);
                        retReceiver.recBytes = null;
                        retReceiver.recBytes = tmpUnionInfo;
                    }

                    int tmpToReadLen = retReceiver.contentLength + retReceiver.contentStartIndex - tmpOffSet;
                    if (tmpToReadLen <= 0)
                    {
                        retReceiver.isCompleted = true;
                        break;
                    }
                }
                else if(retReceiver.recBytes.length - tmpOffSet < 1024){//扩展
                    byte[] tmpUnionInfo2 = new byte[tmpOffSet + 20480];
                    System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo2, 0, tmpOffSet);
                    retReceiver.recBytes = null;
                    retReceiver.recBytes = tmpUnionInfo2;
                }else if (retReceiver.contentLength == 0 && retReceiver.contentStartIndex >= 0){
                    retReceiver.isCompleted = true;
                    break;
                }
            }
            /*tmpOutput.close();
            tmpInput.close();*/
            //if(tmpReceiver.contentStartIndex>=0){
            //	retStr[1] = new String(retReceiver.reqBytes, retReceiver.contentStartIndex,retReceiver.contentLength,retReceiver.charsetName);
            //}
            //else{
            //	retStr[1] = "未能正常识别报文长度";//这里需将已接收的加到日志
            //}
        }
        catch (IOException e) {
            retReceiver.connMsg = LogHelper.getStackTrace(e);
            FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
        }/*finally{
			socket.close();
		}*/
        return retReceiver;
    }
	
	public TcpReceiver sendMessage(byte[] p_headBytes, byte[] p_bodyBytes) throws Exception{
		//String[] retStr = new String[]{"",""};
		TcpReceiver retReceiver = new TcpReceiver();
		if(initContentStartIndex != 0){
			retReceiver.contentStartIndex = initContentStartIndex;
		}
		try {
			socket = new Socket(ip, port);
			socket.setSoTimeout(timeoutMil);//180000
		}
		catch (Exception e) {
			retReceiver.connState = ConnState.FAIL;
			retReceiver.connMsg = e.getMessage();
			return retReceiver;
		}
		try {
			OutputStream tmpOutput = socket.getOutputStream();
			if(p_headBytes!=null){
				tmpOutput.write(p_headBytes);
			}
			tmpOutput.write(p_bodyBytes);
			tmpOutput.flush();
			InputStream tmpInput = socket.getInputStream();
			
			retReceiver.recBytes = new byte[2048];//2K
			int tmpOffSet = 0;
            
			while(!retReceiver.isCompleted){
				int tmpReadLen = tmpInput.read(retReceiver.recBytes, tmpOffSet, retReceiver.recBytes.length - tmpOffSet);
				if(tmpReadLen<=0){
					break;
				}
				tmpOffSet += tmpReadLen;
				retReceiver.readedLength = retReceiver.readedLength + tmpReadLen;
				if(retReceiver.contentLength == -1 || retReceiver.contentStartIndex < 0){
					tcpClient.getContentLength(retReceiver);
				}
				
				if (retReceiver.contentLength > 0)
                {
                    if (retReceiver.recBytes.length < retReceiver.contentLength + retReceiver.contentStartIndex)
                    {
                        byte[] tmpUnionInfo = new byte[retReceiver.contentLength + retReceiver.contentStartIndex];//一次性分配内存
        				System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo, 0, tmpOffSet);
        				retReceiver.recBytes = null;
        				retReceiver.recBytes = tmpUnionInfo;
                    }
                    
                    int tmpToReadLen = retReceiver.contentLength + retReceiver.contentStartIndex - tmpOffSet;
                    if (tmpToReadLen <= 0)
                    {
                    	retReceiver.isCompleted = true;
                    	break;
                    }
                }
				else if(retReceiver.recBytes.length - tmpOffSet < 1024){//扩展
					byte[] tmpUnionInfo2 = new byte[tmpOffSet + 20480];
					System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo2, 0, tmpOffSet);
					retReceiver.recBytes = null;
					retReceiver.recBytes = tmpUnionInfo2;
				}else if (retReceiver.contentLength == 0 && retReceiver.contentStartIndex >= 0){
					retReceiver.isCompleted = true;
                	break;
				}
			}
			tmpOutput.close();
			tmpInput.close();
			//if(tmpReceiver.contentStartIndex>=0){
			//	retStr[1] = new String(retReceiver.reqBytes, retReceiver.contentStartIndex,retReceiver.contentLength,retReceiver.charsetName);
			//}
			//else{
			//	retStr[1] = "未能正常识别报文长度";//这里需将已接收的加到日志
			//}
		}
		catch (IOException e) {
			retReceiver.connMsg = LogHelper.getStackTrace(e);
			FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
		}finally{
			socket.close();
		}
		return retReceiver;
	}
	
	public TcpReceiver sendMessage(String message, String charset) throws Exception {
		byte[] sendBytes = message.getBytes(charset);
		return sendMessage(null, sendBytes);
	}

	/*
	public TcpReceiver sendMessage2(String message,String charset) {
		TcpReceiver retReceiver = new TcpReceiver();
		Socket socket = null;
		InputStream is = null;
		OutputStream os = null;
		String returnMessage = null;
		BufferedWriter bwr = null;
		BufferedReader brr = null;
		StringBuilder returnString = new StringBuilder();

		try {
			SocketAddress socketAddress = new InetSocketAddress(ip, port);
			//变量初始化
			socket = new Socket();
			socket.connect(socketAddress, timeoutMil);
			//modified by zhls 2016/9/20 description:因历史账户明细查询超时，调整与银企平台超时时长
			socket.setSoTimeout(timeoutMil);

			is = socket.getInputStream();
			os = socket.getOutputStream();

            //自整个项目字符集转码utf-8之后，调度的字符集默认依旧默认gbk 2012-7-9 wy
			bwr = new BufferedWriter(new OutputStreamWriter(os, charset));
			//brr = new BufferedReader(new InputStreamReader(is));
			brr = new BufferedReader(new InputStreamReader(is, charset));

			//向银行平台发送请求报文
			//log.info("发送报文：send message" + message);
			bwr.write(message + "\0");
			bwr.flush();
			//接收银行平台返回的应答报文
			String line = null;
			while ((line = brr.readLine()) != null) {
				returnString.append(line);
			}
			returnMessage = returnString.toString();
			if (returnMessage != null) {
				returnMessage = returnMessage.trim();
			}
			retReceiver.connMsg = returnMessage;
		} catch (Throwable e) {
			retReceiver.connState = ConnState.FAIL;
			retReceiver.connMsg = LogHelper.getStackTrace(e);
			FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
		} finally {
			try {
				if (bwr != null) {
					bwr.close();
				}
				if (brr != null) {
					brr.close();
				}
				if (is != null) {
					is.close();
				}
				if (os != null) {
					os.close();
				}
				if (socket != null) {
					socket.close();
				}
			} catch (IOException e) {
				FGBiz.limitMsg.exception("TcpPortClient."+ip+":"+port, e);
			}
		}
		return retReceiver;
	}
	*/

}
